package com.baiyang.server.service.article.impl;


import com.alibaba.fastjson.JSONObject;
import com.baiyang.server.model.article.ArticleTypeRel;
import com.baiyang.server.model.base.ArticleType;
import com.baiyang.server.model.read.ReadRecord;
import com.baiyang.server.model.system.Resource;
import com.baiyang.server.service.article.ArticleReadNumService;
import com.baiyang.server.service.article.ArticleTypeRelService;
import com.baiyang.server.service.base.ArticleTypeService;
import com.baiyang.server.service.base.ItemUService;
import com.baiyang.server.service.impl.BaseServiceImpl;
import com.baiyang.server.service.read.ReadRecordService;
import com.baiyang.server.service.system.ResourceService;
import com.baiyang.server.tools.Data;
import com.baiyang.server.tools.DataTool;
import com.baiyang.server.tools.FileTool;
import com.baiyang.server.tools.Letter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.baiyang.server.dao.article.ArticleDao;
import com.baiyang.server.model.article.Article;
import com.baiyang.server.service.article.ArticleService;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.*;

/**
 * 
 * @author XVX
 * BY: @Primary 注解帮助生命@Autowired优先注入的实列
 */
@Service	
public class ArticleServiceImpl extends BaseServiceImpl<ArticleDao, Article> implements ArticleService{
    /**上传地址*/
    @Value("${file.upload.path}")
    private String filePath;
    @Autowired
    private ArticleDao articleDao = null;
    @Autowired
    private ResourceService resourceService = null;
    @Autowired
    private ArticleTypeRelService articleTypeRelService = null;
    @Autowired
    private ArticleReadNumService articleReadNumService = null;
    @Autowired
    private ArticleTypeService articleTypeService;
    @Autowired
    private ItemUService itemUService = null;
    @Autowired
    private ReadRecordService readRecordService = null;
    /**
     * 1. 将文章内容写入到本地
     * 2. 将文章基本信息写入到数据库
     * 3. 将文章资源信息写入到数据库（文章内容，和封面图片信息）
     * 4. 将文章类型信息写入数据库
     * @param article
     * @param letter
     */
    @Override
    @Transactional
    public void insertArticle(Article article, Letter<String> letter) {
        // 文章内容HTML写到本地
        String content = DataTool.createUUID() + ".by";
        String ymd = DataTool.sdf_ymd.format(new Date());
        String path = filePath + File.separator + ymd;
        if(!FileTool.write(path,content,article.getContent())){
            letter.setResult("FAIL");
            letter.setDetail("内容写入本地出错");
            return ;
        }
        // 文章基本信息写入本地
        articleDao.insert(article);
        //资源记录数据库
        //1.by资源
        Resource resourceHtml = new Resource();
        resourceHtml.setId(DataTool.createUUID());
        resourceHtml.setCreateBy(article.getAuthorId());
        resourceHtml.setRelationId(article.getId());
        resourceHtml.setRelationType("CONTENT");
        resourceHtml.setType("TEXT");
        resourceHtml.setPath(ymd + File.separator + content);
        resourceService.insert(resourceHtml);
        //2.图片资源
        Resource resourcePic = new Resource();
        resourcePic.setId(DataTool.createUUID());
        resourcePic.setCreateBy(article.getAuthorId());
        resourcePic.setRelationId(article.getId());
        resourcePic.setRelationType("TITLE_PIC");
        resourcePic.setType("PIC");
        resourcePic.setPath(article.getCoverPic());
        resourceService.insert(resourcePic);
        // 类型信息写入数据库
        List<ArticleTypeRel> rels = new ArrayList<>();
        article.getArticleTypes().forEach(e->{
            ArticleTypeRel rel = new ArticleTypeRel();
            rel.setId(DataTool.createUUID());
            rel.setTypeId(e.getId());
            rel.setArticleId(article.getId());
            rels.add(rel);
        });
        articleTypeRelService.insertBatch(rels);
        // 插入成功
        letter.setDetail("数据插入成功！");
        letter.setResult("SUCCESS");
    }

    @Override
    public String getContent(String articleId) {
        Resource resource = new Resource();
        resource.setRelationId(articleId);
        resource.setType("TEXT");
        resource.setRelationType("CONTENT");
        resource = resourceService.selectOne(resource);
        if(resource != null){
            String path = resource.getPath();
            String text = FileTool.read(filePath + File.separator + path);
            return text;
        }
        return null;
    }

    private static final int ARTICLE = 0x11;
    private static final int FEATURED = 0x12;
    private static final int LEADERBOARD = 0x13;
    private static final int LABEL = 0x14;
    /**
     * 获取排行榜，阅读数量前八的书籍信息
     * @apiNote 1.根绝文章阅读数量表获取阅读数量最多的前八本书籍
     *          2.根基获取的文章ID获取书籍详细信息
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public List<JSONObject> getLeaderboard() {
        List<JSONObject> list = new ArrayList<>();
        // 设置标题信息
        JSONObject label = new JSONObject();
        label.put("label","文章排行榜");
        label.put("viewType",LABEL);
        // 获取阅读数量前八的书籍
        List<String> articleIds = articleReadNumService.getTop(8);
        // 根基Id 信息获取书籍信息
        List<JSONObject> articles = articleDao.selectByIds(articleIds);
        if(DataTool.isBlank(articles)){
            return null;
        }else{
            list.addAll(articles);
            List<JSONObject> results = new ArrayList<>();
            results.add(label);
            for(int i = 0 ; i < list.size() ; i = i +2){
                JSONObject left = list.get(i);
                setDetail(left);
                left.put("ranking",String.valueOf(i+1));
                JSONObject right = null;
                if(i + 1 >= list.size()){
                }else{
                    right = list.get(i+1);
                    setDetail(right);
                    right.put("ranking",String.valueOf(i+2));
                }
                JSONObject result = new JSONObject();
                result.put("left",left);
                result.put("right",right);
                result.put("viewType",LEADERBOARD);
                results.add(result);
            }
            return results;
        }
    }

    /**
     * 基于用户的协同过滤算法获取到用户喜爱的前十的书籍
     * @param i
     * @param userId
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public List<JSONObject> getFeatured(int i, String userId) {
        List<JSONObject> list = new ArrayList<>();
        // 设置标题信息
        JSONObject label = new JSONObject();
        label.put("label","精选");
        label.put("viewType",LABEL);
        List<String> ids = itemUService.selectUserIdsByUserId(userId);
        if(!DataTool.isBlank(ids)){
            //获取本人的阅读记录
            ReadRecord record = new ReadRecord();
            record.setUserId(userId);
            List<ReadRecord> myRecord = readRecordService.selectList(record);
            //获取其他关联用户的前十本阅读记录
            List<ReadRecord> otherRecord = readRecordService.selectByUserIds(ids,10);
            if(otherRecord != null){
                List<String> articleIds = new ArrayList<>();
                if(DataTool.isBlank(myRecord)){
                    otherRecord.forEach(e->{
                        articleIds.add(e.getArticleId());
                    });
                }else{
                    otherRecord.forEach(e->{
                        boolean flag = true;
                        for (ReadRecord readRecord : myRecord) {
                            if(e.getArticleId().equals(readRecord.getArticleId())){
                                flag = false;
                                break;
                            }
                        }
                        if(flag){
                            articleIds.add(e.getArticleId());
                        }
                    });
                }
                // 根基Id 信息获取书籍信息
                if(DataTool.isBlank(articleIds)){
                    return null;
                }
                List<JSONObject> articles = articleDao.selectByIds(articleIds);
                if(DataTool.isBlank(articles)){
                    return null;
                }else{
                    articles.forEach(e->{
                        e.put("viewType",FEATURED);
                        setDetail(e);
                    });
                    list.add(label);
                    list.addAll(articles);
                    return list;
                }
            }
        }
        return null;
    }

    /**
     * 最新的前二十书籍
     * @param i
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public List<JSONObject> getArticle(int i) {
        List<JSONObject> list = new ArrayList<>();
        // 设置标题信息
        JSONObject label = new JSONObject();
        label.put("label","最新文章");
        label.put("viewType",LABEL);
        list.add(label);
        int start = (i - 1) * 20;
        int size = 20;
        // 获取最新的二十篇文章
        List<JSONObject> articles = articleDao.getArticle(start,size);
        if(DataTool.isBlank(articles)){
            return null;
        }else{
            articles.forEach(e->{
                e.put("viewType",ARTICLE);
                setDetail(e);
            });
            list.addAll(articles);
            return list;
        }
    }

    @Override
    public List<Article> getArticleByType(JSONObject object) {
        int pageStart = (object.getIntValue("pageOn")-1) * object.getIntValue("pageSize");
        object.put("pageStart",pageStart);
        List<Article> list = articleDao.getArticleByType(object);
        list.forEach(e->{
            setDetail(e);
        });
        return list;
    }

    @Override
    public List<Article> getArticleByAuthor(String authorId) {
        List<Article> list = articleDao.getArticleByAuthor(authorId);
        list.forEach(e->{
            setDetail(e);
        });
        return list;
    }

    /**
     * 设置类型和文章url
     * @param object
     */
    private void setDetail(JSONObject object){
        ArticleTypeRel rel = new ArticleTypeRel();
        rel.setArticleId(object.getString("id"));
        List<ArticleTypeRel> rels = articleTypeRelService.selectList(rel);
        List<String> ids = new ArrayList<>();
        rels.forEach(r->{
            ids.add(r.getTypeId());
        });
        List<ArticleType> articleTypes = articleTypeService.selectByIds(ids);
        StringBuilder sb = new StringBuilder();
        articleTypes.forEach(e->{
            sb.append(e.getTypeName());
        });
        object.put("articleType",sb);
        // 设置图片url
        Resource resourcePic = new Resource();
        resourcePic.setRelationId(object.getString("id"));
        resourcePic.setRelationType("TITLE_PIC");
        resourcePic.setType("PIC");
        resourcePic = resourceService.selectOne(resourcePic);
        object.put("pic",resourcePic.getPath());
    }

    /**
     * 设置类型和文章url
     */
    public void setDetail(Article article){
        ArticleTypeRel rel = new ArticleTypeRel();
        rel.setArticleId(article.getId());
        List<ArticleTypeRel> rels = articleTypeRelService.selectList(rel);
        List<String> ids = new ArrayList<>();
        rels.forEach(r->{
            ids.add(r.getTypeId());
        });
        List<ArticleType> articleTypes = articleTypeService.selectByIds(ids);
        StringBuilder sb = new StringBuilder();
        articleTypes.forEach(e->{
            sb.append(e.getTypeName());
        });
        article.setArticleTypes(articleTypes);
        article.setTypesName(sb.toString());
        // 设置图片url
        Resource resourcePic = new Resource();
        resourcePic.setRelationId(article.getId());
        resourcePic.setRelationType("TITLE_PIC");
        resourcePic.setType("PIC");
        resourcePic = resourceService.selectOne(resourcePic);
        article.setCoverPic(resourcePic.getPath());
    }

    @Override
    public Article getArticleById(Article article) {
        article = this.selectOne(article);
        if(article !=null){
            setDetail(article);
            //1.html资源
            Resource resourceHtml = new Resource();
            resourceHtml.setRelationId(article.getId());
            resourceHtml.setRelationType("CONTENT");
            resourceHtml.setType("TEXT");
            resourceHtml = resourceService.selectOne(resourceHtml);
            article.setContent(FileTool.read(filePath + File.separator + resourceHtml.getPath()));
        }
        return article;
    }

    @Override
    @Transactional
    public void alter(Article article, Letter<String> letter) {
        // 文章内容HTML写到本地
        String content = DataTool.createUUID() + ".by";
        String ymd = DataTool.sdf_ymd.format(new Date());
        String path = filePath + File.separator + ymd;
        if(!FileTool.write(path,content,article.getContent())){
            letter.setResult("FAIL");
            letter.setDetail("内容写入本地出错");
            return ;
        }
        // 文章基本信息修改
        articleDao.updateById(article);
        //资源记录数据库
        //1.html资源
        Resource resourceHtml = new Resource();
        // 删除原有
        resourceHtml.setRelationId(article.getId());
        resourceService.delete(resourceHtml);
        resourceHtml.setId(DataTool.createUUID());
        resourceHtml.setCreateBy(article.getAuthorId());
        resourceHtml.setRelationId(article.getId());
        resourceHtml.setRelationType("CONTENT");
        resourceHtml.setType("TEXT");
        resourceHtml.setPath(ymd + File.separator + content);
        resourceService.insert(resourceHtml);
        //2.图片资源
        Resource resourcePic = new Resource();
        resourcePic.setId(DataTool.createUUID());
        resourcePic.setCreateBy(article.getAuthorId());
        resourcePic.setRelationId(article.getId());
        resourcePic.setRelationType("TITLE_PIC");
        resourcePic.setType("PIC");
        resourcePic.setPath(article.getCoverPic());
        resourceService.insert(resourcePic);
        // 类型信息写入数据库
        // 删除原有类型
        ArticleTypeRel articleTypeRel = new ArticleTypeRel();
        articleTypeRel.setArticleId(article.getId());
        articleTypeRelService.delete(articleTypeRel);
        List<ArticleTypeRel> rels = new ArrayList<>();
        article.getArticleTypes().forEach(e->{
            ArticleTypeRel rel = new ArticleTypeRel();
            rel.setId(DataTool.createUUID());
            rel.setTypeId(e.getId());
            rel.setArticleId(article.getId());
            rels.add(rel);
        });
        articleTypeRelService.insertBatch(rels);
        // 插入成功
        letter.setDetail("数据修改成功！");
        letter.setResult("SUCCESS");
    }

    @Override
    public List<Map<String, Object>> getReadNum(Article article) {
        //获取作者的所有文章
        article.setState("2");
        List<Article> list = articleDao.selectList(article);
        //获取每个文章当日的阅读情况
        List<Map<String,Object>> mapList = new ArrayList<>();
        String date = DataTool.sdf_ymd.format(new Date());
        list.forEach(e->{
            Integer num = readRecordService.getTodayReadNum(e.getId(),date);
            Integer allNum = articleReadNumService.selectAllNum(e.getId());
            Map<String,Object> map = new HashMap<>();
            map.put("article",e.getArticleName());
            map.put("num",num);
            map.put("allNum",allNum);
            mapList.add(map);
        });
        return mapList;
    }

    @Override
    public Article getNewArticle(Article article) {
        return articleDao.getNewArticle(article);
    }

}
